<?php

namespace fastphp;


/**
 * 响应处理类
 * 负责生成和发送HTTP响应，符合MVC架构中的响应处理层
 */
class Response
{
    /**
     * 响应状态码
     * @var int
     */
    protected $statusCode = 200;
    
    /**
     * 响应头信息
     * @var array
     */
    protected $headers = [];
    
    /**
     * 响应内容类型
     * @var string
     */
    protected $contentType = 'text/html';
    
    /**
     * 响应内容编码
     * @var string
     */
    protected $charset = 'utf-8';
    
    /**
     * 设置HTTP状态码
     * @param int $code HTTP状态码
     * @return $this
     */
    public function status(int $code): self
    {
        $this->statusCode = $code;
        http_response_code($code);
        return $this;
    }
    
    /**
     * 设置响应头
     * @param string $name 头信息名称
     * @param string $value 头信息值
     * @return $this
     */
    public function header(string $name, string $value): self
    {
        $this->headers[$name] = $value;
        header("$name: $value");
        return $this;
    }
    
    /**
     * 设置内容类型
     * @param string $type 内容类型
     * @param string $charset 字符集
     * @return $this
     */
    public function type(string $type, string $charset = null): self
    {
        $this->contentType = $type;
        $this->charset = $charset ?? $this->charset;
        return $this->header('Content-Type', "$type;charset=$this->charset");
    }
    
    /**
     * 设置JSON响应头
     * @param string $charset 字符集
     * @return $this
     */
    public function jsonType(string $charset = null): self
    {
        return $this->type('application/json', $charset);
    }
    
    /**
     * 设置HTML响应头
     * @param string $charset 字符集
     * @return $this
     */
    public function htmlType(string $charset = null): self
    {
        return $this->type('text/html', $charset);
    }
    
    /**
     * 设置XML响应头
     * @param string $charset 字符集
     * @return $this
     */
    public function xmlType(string $charset = null): self
    {
        return $this->type('application/xml', $charset);
    }
    
    /**
     * 发送JSON响应
     * @param mixed $data 响应数据
     * @param int $code 状态码
     * @return $this
     */
    public function json($data, int $code = 200): self
    {
        $this->status($code);
        $this->jsonType();
        
        // 对数据进行安全过滤
        $data = $this->sanitizeData($data);
        echo json_encode($data, JSON_UNESCAPED_UNICODE);
        
        return $this;
    }
    
    /**
     * 创建标准API响应格式
     * @param string $msg 响应消息
     * @param array $data 响应数据
     * @param int $code 响应码
     * @return $this
     */
    public function create($msg, $data = [], $code = 200): self
    {
        return $this->json([
            'code' => $code,
            'msg' => $msg,
            'data' => $data
        ], $code);
    }
    
    /**
     * 发送HTML响应
     * @param string $content HTML内容
     * @param int $code 状态码
     * @return $this
     */
    public function html(string $content, int $code = 200): self
    {
        $this->status($code);
        $this->htmlType();
        echo $content;
        return $this;
    }
    
    /**
     * 重定向到指定URL
     * @param string $url 重定向地址
     * @param int $code 状态码 (301, 302)
     * @return void
     */
    public function redirect(string $url, int $code = 302): void
    {
        $this->status($code);
        $this->header('Location', $url);
        exit;
    }
    
    /**
     * 设置cookie
     * @param string $name cookie名称
     * @param string $value cookie值
     * @param int $expire 过期时间
     * @param string $path 路径
     * @param string $domain 域名
     * @param bool $secure 是否安全连接
     * @param bool $httponly 是否仅HTTP
     * @return $this
     */
    public function cookie(string $name, string $value = '', int $expire = 0, string $path = '/', string $domain = '', bool $secure = false, bool $httponly = false): self
    {
        setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
        return $this;
    }
    
    /**
     * 清空cookie
     * @param string $name cookie名称
     * @param string $path 路径
     * @param string $domain 域名
     * @return $this
     */
    public function clearCookie(string $name, string $path = '/', string $domain = ''): self
    {
        return $this->cookie($name, '', time() - 3600, $path, $domain);
    }
    
    /**
     * 对输出数据进行安全过滤
     * @param mixed $data 需要过滤的数据
     * @return mixed 过滤后的数据
     */
    protected function sanitizeData($data)
    {
        if (is_array($data)) {
            return array_map([$this, 'sanitizeData'], $data);
        } elseif (is_string($data)) {
            // 基本的HTML实体编码，防止XSS攻击
            return htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
        }
        return $data;
    }
    
    /**
     * 中止执行并输出错误信息
     * @param string $message 错误消息
     * @param int $code 状态码
     * @return void
     */
    public function abort(string $message, int $code = 500): void
    {
        $this->status($code);
        $this->htmlType();
        echo $message;
        exit;
    }
}